{
 "cells": [
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "GoogLeNet\n",
    "含有并行连结的网络"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import d2lzh as d2l\n",
    "from mxnet import gluon, init, nd\n",
    "from mxnet.gluon import nn\n",
    "\n",
    "class Inception(nn.Block):\n",
    "    # c1 - c4为每条线路里的层的输出通道数\n",
    "    def __init__(self, c1, c2, c3, c4, **kwargs):\n",
    "        super(Inception, self).__init__(**kwargs)\n",
    "        # 线路1，单1 x 1卷积层\n",
    "        self.p1_1 = nn.Conv2D(c1, kernel_size=1, activation='relu')\n",
    "        # 线路2，1 x 1卷积层后接3 x 3卷积层\n",
    "        self.p2_1 = nn.Conv2D(c2[0], kernel_size=1, activation='relu')\n",
    "        self.p2_2 = nn.Conv2D(c2[1], kernel_size=3, padding=1,\n",
    "                              activation='relu')\n",
    "        # 线路3，1 x 1卷积层后接5 x 5卷积层\n",
    "        self.p3_1 = nn.Conv2D(c3[0], kernel_size=1, activation='relu')\n",
    "        self.p3_2 = nn.Conv2D(c3[1], kernel_size=5, padding=2,\n",
    "                              activation='relu')\n",
    "        # 线路4，3 x 3最大池化层后接1 x 1卷积层\n",
    "        self.p4_1 = nn.MaxPool2D(pool_size=3, strides=1, padding=1)\n",
    "        self.p4_2 = nn.Conv2D(c4, kernel_size=1, activation='relu')\n",
    "\n",
    "    def forward(self, x):\n",
    "        p1 = self.p1_1(x)\n",
    "        p2 = self.p2_2(self.p2_1(x))\n",
    "        p3 = self.p3_2(self.p3_1(x))\n",
    "        p4 = self.p4_2(self.p4_1(x))\n",
    "        return nd.concat(p1, p2, p3, p4, dim=1)  # 在通道维上连结输出"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "GoogLeNet模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "b1 = nn.Sequential()\n",
    "b1.add(nn.Conv2D(64, kernel_size=7, strides=2, padding=3, activation='relu'),\n",
    "      nn.MaxPool2D(pool_size=3, strides=2, padding=1))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "b2 = nn.Sequential()\n",
    "b2.add(nn.Conv2D(64, kernel_size=1, activation='relu'),\n",
    "       nn.Conv2D(192, kernel_size=3, padding=1, activation='relu'),\n",
    "       nn.MaxPool2D(pool_size=3, strides=2, padding=1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "b3 = nn.Sequential()\n",
    "b3.add(Inception(64, (96, 128), (16, 32), 32),\n",
    "       Inception(128, (128, 192), (32, 96), 64),\n",
    "       nn.MaxPool2D(pool_size=3, strides=2, padding=1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "b4 = nn.Sequential()\n",
    "b4.add(Inception(192, (96, 208), (16, 48), 64),\n",
    "       Inception(160, (112, 224), (24, 64), 64),\n",
    "       Inception(128, (128, 256), (24, 64), 64),\n",
    "       Inception(112, (144, 288), (32, 64), 64),\n",
    "       Inception(256, (160, 320), (32, 128), 128),\n",
    "       nn.MaxPool2D(pool_size=3, strides=2, padding=1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "b5 = nn.Sequential()\n",
    "b5.add(Inception(256, (160, 320), (32, 128), 128),\n",
    "       Inception(384, (192, 384), (48, 128), 128),\n",
    "       nn.GlobalAvgPool2D())\n",
    "\n",
    "net = nn.Sequential()\n",
    "net.add(b1, b2, b3, b4, b5, nn.Dense(10))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "sequential0 output shape:\t (1, 64, 132, 132)\n",
      "sequential1 output shape:\t (1, 192, 66, 66)\n",
      "sequential2 output shape:\t (1, 480, 33, 33)\n",
      "sequential3 output shape:\t (1, 832, 17, 17)\n",
      "sequential4 output shape:\t (1, 1024, 1, 1)\n",
      "dense0 output shape:\t (1, 10)\n"
     ]
    }
   ],
   "source": [
    "X = nd.random.uniform(shape=(1, 1, 528, 528))\n",
    "net.initialize()\n",
    "for layer in net:\n",
    "    X = layer(X)\n",
    "    print(layer.name, 'output shape:\\t', X.shape)"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "训练模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "training on cpu(0)\n"
     ]
    }
   ],
   "source": [
    "lr, num_epochs, batch_size, ctx = 0.1, 5, 128, d2l.try_gpu()\n",
    "net.initialize(force_reinit=True, ctx=ctx, init=init.Xavier())\n",
    "trainer = gluon.Trainer(net.collect_params(), 'sgd', {'learning_rate': lr})\n",
    "train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size, resize=96)\n",
    "d2l.train_ch5(net, train_iter, test_iter, batch_size, trainer, ctx,\n",
    "             num_epochs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
